<?php

namespace App\Kuafu\Banner\Service;

use App\Kuafu\Banner\Enum\BannerCodeEnum;
use App\Kuafu\Banner\Enum\BannerEnum;
use App\Kuafu\Banner\Exceptions\BannerException;
use App\Kuafu\Banner\Model\BannerCommonModel;
use App\Kuafu\Banner\Model\BannerCommonShopMappingsModel;
use App\Kuafu\Banner\Resources\BannerListResource;
use App\Kuafu\Base\Enum\DBEnum;
use App\Kuafu\Base\Model\BaseModel;
use App\Kuafu\Base\Service\BaseService;
use App\Kuafu\Common\Service\CommonService;
use App\Kuafu\Config\Model\ConfigModel;
use App\Kuafu\Config\Service\ConfigClientService;
use App\Kuafu\Config\Service\ConfigService;
use App\Kuafu\CouponPackage\Enum\CouponPackageEnum;
use App\Kuafu\Mqtt\Service\MqttQueueService;
use App\Kuafu\Product\Model\Product;
use App\Kuafu\Product\Service\ProductService;
use App\Kuafu\Shop\Enum\DeviceCacheEnum;
use App\Kuafu\Shop\Model\CameraModel;
use App\Kuafu\Shop\Model\Shop;
use App\Kuafu\Shop\Service\ShopService;
use Exception;
use Illuminate\Support\Facades\DB;

class BannerCommonService extends BaseService
{

    /**
     * 获取banner配置
     *
     * @throws Exception
     */
    public static function bannerConfig()
    {
        try {
            return [
                "bannerType"   => [
                    [
                        "value"    => "KF-ORDER",
                        "key"      => "夸父点餐",
                        "children" => enumToSelection(BannerEnum::TYPE_ORDER_GROUP)
                    ],
                    [
                        "value"    => "KF-POS",
                        "key"      => "夸父收银",
                        "children" => enumToSelection(BannerEnum::TYPE_POS_GROUP)
                    ],
                    [
                        "value"    => "KF-TV",
                        "key"      => "夸父商屏",
                        "children" => enumToSelection(BannerEnum::TYPE_TV_GROUP)
                    ],
                    [
                        "value"    => "KF-TV-MATERIAL",
                        "key"      => "商屏素材",
                        "children" => enumToSelection(BannerEnum::TYPE_TV_MATERIAL_GROUP)
                    ]
                ],
                "resourceType" => enumToSelection(BannerCommonModel::RESOURCE_TYPE_TEXT)
            ];
        } catch (\Exception $exception) {
            handleException($exception, "获取banner配置失败");
        }
    }

    /**
     * 广告添加
     *
     * @param int $brandId
     * @param int $uid
     * @param array $bannerParams
     * @param array $bannerShopParams
     * @throws BannerException
     */
    public static function insert(int $brandId, int $uid, array $bannerParams, array $bannerShopParams)
    {
        try {
            DB::beginTransaction();

            $bannerParams = self::bannerCommonOperate($bannerParams);
            $bannerId     = BannerCommonModel::query()->insertGetId(array_merge($bannerParams, [
                'brandId'      => $brandId,
                'createdAt'    => time(),
                'createdByUid' => $uid
            ]));

            $bannerShopMappingInsert = [];
            array_map(function ($shopId) use (&$bannerShopMappingInsert, $bannerId, $uid) {
                array_push($bannerShopMappingInsert, [
                    'shopId'       => $shopId,
                    'bannerId'     => $bannerId,
                    'createdAt'    => time(),
                    'createdByUid' => $uid
                ]);
            }, $bannerShopParams['shopInfo']);
            BannerCommonShopMappingsModel::query()->insert($bannerShopMappingInsert);

            DB::commit();
            DeviceCacheEnum::batchRmDeviceShopTvAdvCache();

            BannerCommonService::sendBannerConfigUpdateMQTT($bannerId);
        } catch (Exception $exception) {
            DB::rollBack();
            throw new BannerException(BannerCodeEnum::ERR_BANNER_DB_ADD);
        }
    }


    /**
     * 广告编辑
     *
     * @param int $brandId
     * @param int $uid
     * @param array $bannerParams
     * @param array $bannerShopParams
     * @throws BannerException
     */
    public static function edit(int $brandId, int $uid, array $bannerParams, array $bannerShopParams)
    {
        try {
            DB::beginTransaction();
            $bannerId     = $bannerParams['id'];
            $bannerParams = self::bannerCommonOperate($bannerParams);

            $bannerInfo = BannerCommonModel::query()->where('id', $bannerId)->select(['id', 'type', 'status'])->first();
            BannerCommonModel::query()->where('id', $bannerId)->update(array_merge($bannerParams, [
                'brandId'      => $brandId,
                'updatedAt'    => time(),
                'updatedByUid' => $uid
            ]));

            BannerCommonShopMappingsModel::query()
                                         ->where('bannerId', $bannerId)
                                         ->where('type', BannerCommonShopMappingsModel::TYPE_SYSTEM)
                                         ->update([
                                             'isDeleted'    => BaseModel::DELETE_YES,
                                             'updatedAt'    => time(),
                                             'updatedByUid' => $uid
                                         ]);
            $bannerShopMappingInsert = [];
            array_map(function ($shopId) use (&$bannerShopMappingInsert, $bannerId, $uid) {
                array_push($bannerShopMappingInsert, [
                    'shopId'       => $shopId,
                    'bannerId'     => $bannerId,
                    'createdAt'    => time(),
                    'createdByUid' => $uid
                ]);
            }, $bannerShopParams['shopInfo']);
            BannerCommonShopMappingsModel::query()->insert($bannerShopMappingInsert);
            //判断商屏素材-单品 有没有关联数据
            if ($bannerInfo->type == BannerEnum::TYPE_TV_MATERIAL_2) {
                $imgs       = json_decode($bannerParams['imgs'], true);
                $defaultImg = '';
                foreach ($imgs as $v) {
                    if (isset($v['price']) && $v['price'] == -1) {
                        $defaultImg = $v['img'] ?? "";
                        break;
                    }
                }
                self::updateBannerMaterialDo($bannerId, $bannerInfo->status, $defaultImg);
            }
            DB::commit();
            DeviceCacheEnum::batchRmDeviceShopTvAdvCache();

            // 推送 MQ, 直营和加盟 类型未实现
            BannerCommonService::sendBannerConfigUpdateMQTT($bannerId);

        } catch (Exception $exception) {
            DB::rollBack();
            throw new BannerException(BannerCodeEnum::ERR_BANNER_DB_SET);
        }
    }

    /**
     * 状态修改
     *
     * @param $requestParams
     * @param $uid
     * @throws BannerException
     */
    public static function status($uid, $requestParams)
    {
        try {
            $type = BannerCommonModel::query()->where('id', $requestParams['id'])->value('type');
            BannerCommonModel::query()->where('id', $requestParams['id'])->update(
                array_merge($requestParams, [
                    'updatedByUid' => $uid,
                    'updatedAt'    => time()
                ])
            );

            //判断商屏素材-单品 有没有关联数据
            if ($type == BannerEnum::TYPE_TV_MATERIAL_2) {
                self::updateBannerMaterialDo($requestParams['id'], $requestParams['status']);
            }

            DeviceCacheEnum::batchRmDeviceShopTvAdvCache();

        } catch (Exception $exception) {
            throw new BannerException(BannerCodeEnum::ERR_BANNER_DB_SET);
        }
    }


    /**
     * 删除
     *
     * @param $requestParams
     * @param $uid
     * @throws BannerException
     */
    public static function del($uid, $requestParams)
    {
        try {
            DB::beginTransaction();
            $type = BannerCommonModel::query()->where('id', $requestParams['id'])->value('type');
            BannerCommonModel::query()->where('id', $requestParams['id'])->update([
                'updatedByUid' => $uid,
                'updatedAt'    => time(),
                'isDeleted'    => BaseModel::DELETE_YES
            ]);

            BannerCommonShopMappingsModel::query()->where('bannerId', $requestParams['id'])->update([
                'updatedByUid' => $uid,
                'updatedAt'    => time(),
                'isDeleted'    => BaseModel::DELETE_YES
            ]);

            //判断商屏素材-单品 有没有关联数据
            if ($type == BannerEnum::TYPE_TV_MATERIAL_2) {
                self::updateBannerMaterialDo($requestParams['id'], -1);
            }
            DB::commit();

            DeviceCacheEnum::batchRmDeviceShopTvAdvCache();

        } catch (Exception $exception) {
            DB::rollBack();
            throw new BannerException(BannerCodeEnum::ERR_BANNER_DB_DEL);
        }
    }


    /**
     * @param int $pageNum
     * @param int $pageSize
     * @param string $name
     * @param string $type
     * @param string $status
     * @param int $shopId
     * @return array
     */
    public static function index(
        int $pageNum,
        int $pageSize,
        string $name = '',
        string $type = '',
        string $status = '',
        int $shopId = 0
    ): array {
        $pagination = BannerCommonModel::getLists($pageSize, $pageNum, $name, $type, $status, $shopId);
        return [
            'count'    => $pagination->total(),
            'lists'    => BannerListResource::collection($pagination->items()),
            'pageNum'  => $pageNum,
            'pageSize' => $pageSize
        ];
    }

    /**
     * 查询首页图片
     * @param $type
     * @param $shopId
     * @param $shopType
     * @param $field
     * @param $selectType
     * @return array
     */
    public static function getAppletIndexImage($type, $shopId, $shopType, $field, $selectType): array
    {
        $indexBanner = BannerCommonModel::getBannerByType($type, $shopId, $shopType, $field, $selectType);
        if (empty($indexBanner)) {
            $where = ['key' => 'appletIndexImage', 'type' => 'applet'];
            $field = ['value'];
            $info  = ConfigService::getConfigInfoByValue($where, $field);
            $info  = json_decode($info['value'], true);
            $data  = ['image' => $info['image'], 'clickImage' => $info['clickImage']];
        } else {
            $data = [
                'image'      => CommonService::joinImageUrl($indexBanner['img']),
                'clickImage' => CommonService::joinImageUrl($indexBanner['extraImg'])
            ];
        }
        return $data;
    }

    /**
     * 获取小程序弹窗
     * @param $type
     * @param $shopId
     * @param $shopType
     * @param $field
     * @param $selectType
     * @return array|string[]
     */
    public static function getAppletPopImage($type, $shopId, $shopType, $field, $selectType): array
    {
        $popBanner = BannerCommonModel::getBannerByType($type, $shopId, $shopType, $field, $selectType);
        if (empty($popBanner)) {
            return ['popImg' => ''];
        }
        return ['popImg' => CommonService::joinImageUrl($popBanner['img'])];
    }

    /**
     * 查询pos副屏轮播图
     * @param $type
     * @param $shopId
     * @param $shopType
     * @param $field
     * @param $selectType
     * @return array|string[]
     */
    public static function getAuxiliaryScreenRotation($type, $shopId, $shopType, $field, $selectType): array
    {
        $bannerByType = BannerCommonModel::getBannerByType($type, $shopId, $shopType, $field, $selectType);
        if (empty($bannerByType->toArray())) {
            return ConfigClientService::getPosDefaultAuxiliaryScreenRotation();
        }
        $list = [];
        $bannerByType->each(function ($banner) use (&$list) {
            array_push($list, CommonService::joinImageUrl($banner->img));
        });
        return $list;
    }


    /**
     * 单品素材搜索
     * @param string $name
     * @return array
     */
    public static function bannerSearch(string $name): array
    {
        return BannerCommonModel::bannerSearch(BannerEnum::TYPE_TV_MATERIAL_2, $name);
    }

    /**
     * 公共处理操作
     * @param array $bannerParams
     * @return array
     */
    public static function bannerCommonOperate(array $bannerParams): array
    {
        if ($bannerParams['type'] == BannerEnum::TYPE_TV_MATERIAL_1 && $bannerParams['imgs']) {//商屏素材—组合 关联bannerId,形式:,1,2,
            $imgs                         = json_decode($bannerParams['imgs'], true);
            $bannerJoinId                 = array_column($imgs, 'id');
            $bannerJoinId                 = implode(',', $bannerJoinId);
            $bannerParams['bannerJoinId'] = ',' . $bannerJoinId . ',';
        }
        return $bannerParams;
    }


    /**
     * 删除提示,获取关联多少个素材
     * @param int $id
     * @return array
     */
    public static function getCount(int $id): array
    {
        $data = BannerCommonModel::query()
                                 ->where('type', BannerEnum::TYPE_TV_MATERIAL_1)
                                 ->where('bannerJoinId', 'like', '%,' . $id . ',%')
                                 ->limit(3)
                                 ->get()->map(function ($BannerCommonModel) {
                return [
                    'name' => $BannerCommonModel->name,
                ];
            })->toArray();
        return $data ? array_column($data, 'name') : [];
    }

    /**
     * 商屏素材-单品修改/删除时 判断有没有关联数据
     * @param int $id
     * @param int $status
     * @param string $defaultImg
     */
    public static function updateBannerMaterialDo(int $id, int $status, string $defaultImg = '')
    {
        BannerCommonModel::query()
                         ->where('type', BannerEnum::TYPE_TV_MATERIAL_1)
                         ->where('bannerJoinId', 'like', '%,' . $id . ',%')
                         ->chunkById(10, function ($BannerCommonModel) use ($defaultImg, $status, $id) {
                             foreach ($BannerCommonModel as $v) {
                                 $imgs = json_decode($v->imgs, true);
                                 foreach ($imgs as $k => &$img) {
                                     if (isset($img['id']) && $img['id'] == $id) {
                                         if ($status < 0) {//删除
                                             unset($imgs[$k]);
                                         } else {//只修改状态
                                             $img['status'] = $status;
                                         }
                                         if ($defaultImg) {
                                             $img['img'] = $defaultImg;
                                         }
                                     }
                                 }

                                 if ($imgs) {
                                     $bannerJoinId                 = array_column($imgs, 'id');
                                     $bannerJoinId                 = implode(',', $bannerJoinId);
                                     $bannerParams['bannerJoinId'] = ',' . $bannerJoinId . ',';
                                     $bannerParams['imgs']         = json_encode($imgs);
                                 } else {
                                     $bannerParams['imgs']         = json_encode([]);
                                     $bannerParams['bannerJoinId'] = '';
                                 }
                                 BannerCommonModel::query()
                                                  ->where('id', $v->id)
                                                  ->update($bannerParams);
                             }
                         });
    }


    /**
     * 匹配对应的广告图
     * @param int $shopId
     * @param array $productIds
     * @param int $shopMenuId
     * @param array $childIds
     * @return array
     */
    public static function getBannerImgsByMaterial(
        int $shopId,
        array $productIds,
        int $shopMenuId = 0,
        array $childIds = []
    ): array {
        $bannerData = [];
        if (!$shopMenuId) {
            $shopInfo   = ShopService::getShopInfo($shopId);
            $shopMenuId = $shopInfo['menuId'] ?? 0;
        }

        $priceData = Product::query()
                            ->where("menuId", $shopMenuId)
                            ->where("status", 0)
                            ->whereIn("id", $productIds)
                            ->select(['id', 'price'])
                            ->get()->keyBy('id')->toArray();

        BannerCommonModel::query()
                         ->where('type', BannerEnum::TYPE_TV_MATERIAL_2)
                         ->where('status', BannerEnum::STATUS_ON)
                         ->when($childIds, function ($query) use ($childIds) {
                             $query->whereIn('id', $childIds);
                         })
                         ->orderBy('sort')
                         ->orderBy('id', 'desc')
                         ->chunkById(100, function ($bannerCommonModel) use ($priceData, &$bannerData) {
                             foreach ($bannerCommonModel as $v) {
                                 $imgUrl = $defaultImgUrl = '';
                                 $imgs   = json_decode($v->imgs, true);
                                 foreach ($imgs as $img) {
                                     if (isset($img['price'])) {
                                         if ($img['price'] == -1) {
                                             $defaultImgUrl = $img['img'] ?? "";
                                         }
                                         if (isset($img['id']) && isset($priceData[$img['id']]['price']) && $img['price'] == $priceData[$img['id']]['price']) {
                                             $imgUrl = $img['img'];
                                         }
                                     }
                                 }
                                 if (!$imgUrl) {
                                     $imgUrl = $defaultImgUrl;//默认图
                                 }
                                 if (!$imgUrl) {
                                     continue;
                                 }
                                 $bannerData[] = [
                                     'id'           => $v->id,
                                     'name'         => $v->name,
                                     "resourceType" => $v->resourceType,
                                     "url"          => $imgUrl,
                                     "type"         => $v->type,
                                     "typeText"     => BannerEnum::TYPE_MAP[$v->type]
                                 ];
                             }
                         });
        return $bannerData;
    }

    public static function sendBannerConfigUpdateMQTT(int $bannerId)
    {
        $assignType = array_merge(array_keys(BannerEnum::TYPE_TV_GROUP),
            array_keys(BannerEnum::TYPE_TV_MATERIAL_GROUP));

        $bannerInfo = BannerCommonModel::query()
                                       ->whereIn('type', $assignType)
                                       ->where('id', $bannerId)
                                       ->first();
        if (!$bannerInfo) {
            return;
        }

        if (in_array($bannerInfo->type, $assignType)) {

            // 如果是 1, 2, 3, 4类型商屏 更新 MQ
            $shopIds = [];
            switch ($bannerInfo->shopType) {
                case CouponPackageEnum::SHOP_TYPE_ALL:
                case CouponPackageEnum::SHOP_TYPE_FRANCHISE:
                case CouponPackageEnum::SHOP_TYPE_DIRECT:
                    $shopIds = CameraModel::query()
                                          ->where('deviceType', CameraModel::DEVICE_TYPE_TV)
                                          ->pluck('shopId')
                                          ->toArray();
                    break;
                case CouponPackageEnum::SHOP_TYPE_SELECTION:
                default:
                    $shopIds = BannerCommonShopMappingsModel::query()
                                                            ->where('bannerId', $bannerInfo->id)
                                                            ->pluck('shopId')
                                                            ->toArray();
                    break;
            }

            $shopIds = array_unique($shopIds);
            MqttQueueService::updateShopBannerConfig($shopIds);
        }


    }

}
